using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;

namespace ConsolePlayer
{
	public class Extensions
	{

		private static Extensions _instance = null;
		public static Extensions Instance
		{
			get
			{
				if (_instance == null) _instance = new Extensions();
				return _instance;
			}
		}

		public bool Install(string fileName)
		{
			FileInfo info = new FileInfo(fileName);
			string file = info.FullName;

			if( extensionList.ContainsValue(file) )
			{
				Console.WriteLine("extension already exist");
				return false;
			}

			extensionList.Add(extensionList.Count, file);
			return true;
		}

		public bool Uninstall(string fileName)
		{
			FileInfo info = new FileInfo(fileName);
			string file = info.FullName;

			if (!extensionList.ContainsValue(file))
			{
				Console.WriteLine("extension do not exist");
				return false;
			}

			int index = -1;
			foreach (KeyValuePair<int, string> pair in extensionList)
			{
				if( pair.Value == file )
				{
					index = pair.Key;
					break;
				}
			}

			if( index == -1 )
			{
				Console.WriteLine("extension do not exist");
				return false;
			}
			else
			{
				extensionList.Remove(index);
				return true;
			}
		}

		public int Count
		{
			get
			{
				return extensionList.Count;
			}
		}

		public List<object> objList = new List<object>();

		public IExtension this[int index]
		{
			get
			{
				if (index < 0 || index >= extensionList.Count)
				{
					return null;
				}
				else
				{
					string file = extensionList[index];
					//Reflection here
					Assembly asm = Assembly.LoadFrom(file);
					if (asm == null) return null;
					foreach(Type t in asm.GetTypes() )   
					{   
						  if(t.IsClass   &&!t.IsAbstract)     
						  {
							  Type inter = t.GetInterface("IExtension");
							  if (inter == null) continue;
							  MethodInfo method = inter.GetMethod("ParseCommandLine");
							  if (method == null) continue;
							  object o = Activator.CreateInstance(t);
							  if (o != null)
								  return (IExtension)o;
							  else
								  return null;
						  }
    
					}

					return null;
				}

			}
		}
		private string listDataFile;
		private Extensions()
		{
			listDataFile = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
			if (!listDataFile.EndsWith("\\"))
				listDataFile += "\\";
			listDataFile += "consoleplayer\\";
			DirectoryInfo dir = new DirectoryInfo(listDataFile);
			if (!dir.Exists)
				dir.Create();
			listDataFile += "extension.dat";
			if (File.Exists(listDataFile))
			{
				FileStream fileStream = new FileStream(listDataFile, FileMode.Open, FileAccess.Read, FileShare.Read);
				BinaryFormatter b = new BinaryFormatter();//SoapFormatter
				extensionList = (Dictionary<int, string>)b.Deserialize(fileStream);
				if (extensionList == null)
					extensionList = new Dictionary<int, string>();
				fileStream.Close();

			}
			else
			{
				extensionList = new Dictionary<int, string>();
			}

			
		}
		private Dictionary<int, string> extensionList = null;

		public void Flush()
		{
			BinaryFormatter b=new BinaryFormatter();
			FileStream fileStream = new FileStream(listDataFile, FileMode.Create);
			b.Serialize(fileStream, extensionList);
			fileStream.Flush();
			fileStream.Close();
		}
	}

	class CommandAddExtension : ICommand
	{
		private PlayerArgs _args = null;
		public CommandAddExtension(PlayerArgs args)
		{
			_args = args;
		}
		#region ICommand Members

		public void Action()
		{
			Extensions.Instance.Install(_args.destFile);
		}

		#endregion
	}

	class CommandDelExtension : ICommand
	{
		private PlayerArgs _args = null;
		public CommandDelExtension(PlayerArgs args)
		{
			_args = args;
		}
		#region ICommand Members

		public void Action()
		{
			Extensions.Instance.Uninstall(_args.destFile);
		}

		#endregion
	}
}
